home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / clients / editres / wtree.c < prev   
Encoding:
C/C++ Source or Header  |  1994-08-12  |  19.3 KB  |  735 lines

  1. /*
  2.  * $XConsortium: wtree.c,v 1.13 91/07/09 12:08:53 rws Exp $
  3.  *
  4.  * Copyright 1989 Massachusetts Institute of Technology
  5.  *
  6.  * Permission to use, copy, modify, distribute, and sell this software and its
  7.  * documentation for any purpose is hereby granted without fee, provided that
  8.  * the above copyright notice appear in all copies and that both that
  9.  * copyright notice and this permission notice appear in supporting
  10.  * documentation, and that the name of M.I.T. not be used in advertising or
  11.  * publicity pertaining to distribution of the software without specific,
  12.  * written prior permission.  M.I.T. makes no representations about the
  13.  * suitability of this software for any purpose.  It is provided "as is"
  14.  * without express or implied warranty.
  15.  *
  16.  * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
  17.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
  18.  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  19.  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  20.  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 
  21.  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  22.  */
  23.  
  24. #include <stdio.h>
  25. #ifdef MSDOS
  26. #include "X11/Intrinsc.h"      /* QDK 05/11/1994 12:54pm. */
  27. #else
  28. #include "X11/Intrinsic.h"
  29. #endif
  30. #include <X11/Xutil.h>
  31. #include <X11/StringDefs.h>
  32.  
  33. #include <X11/Xaw/Cardinals.h>
  34. #include <X11/Xaw/Toggle.h>
  35. #include <X11/Xaw/Viewport.h>    
  36. #include <X11/Xaw/Tree.h>
  37.  
  38. #include "editresP.h"
  39.  
  40. extern ScreenData global_screen_data;
  41. extern void SetMessage();
  42.  
  43. static Boolean IsActiveNode();
  44. static void AddChild(), FillNode();
  45. static void AddNode();
  46. static void AddNodeToActiveList(), RemoveNodeFromActiveList();
  47.  
  48. extern void PrepareToLayoutTree(), LayoutTree();
  49.  
  50. extern void _TreeSelectNode(), _TreeActivateNode(), _TreeRelabelNode();
  51. static WNode ** CopyActiveNodes();
  52.  
  53. void TreeToggle();
  54.  
  55. /*    Function Name: BuildVisualTree
  56.  *    Description: Creates the Tree and shows it.
  57.  *    Arguments: tree_parent - parent of the tree widget.
  58.  *                 event - the event that caused this action.
  59.  *    Returns: none.
  60.  */
  61.  
  62. /* ARGSUSED */
  63. void
  64. BuildVisualTree(tree_parent, event)
  65. Widget tree_parent;
  66. Event * event;
  67. {
  68.     WNode * top;
  69.     TreeInfo *CreateTree();
  70.     void AddTreeNode();
  71.     char msg[BUFSIZ];
  72.  
  73.     if (global_tree_info != NULL) {
  74.     XtDestroyWidget(global_tree_info->tree_widget);
  75.     XtFree((char *)global_tree_info->active_nodes);
  76.     XtFree((char *)global_tree_info);
  77.     }
  78.  
  79.     global_tree_info = CreateTree(event);
  80.     top = global_tree_info->top_node;
  81.  
  82.     global_tree_info->tree_widget = XtCreateWidget("tree", treeWidgetClass,
  83.                            tree_parent, NULL, ZERO);
  84.  
  85.     if (top == NULL) {
  86.     SetMessage(global_screen_data.info_label,
  87.            "There is no widget tree to display.");
  88.     return;
  89.     }
  90.  
  91.     AddTreeNode(global_tree_info->tree_widget, top);
  92.  
  93.     if (XtIsRealized(tree_parent)) /* hack around problems in Xt. */
  94.     XtRealizeWidget(global_tree_info->tree_widget);
  95.  
  96.     XtManageChild(global_tree_info->tree_widget);
  97.  
  98.     sprintf(msg, "Widget Tree for client %s(%s).", top->name, top->class);
  99.     SetMessage(global_screen_data.info_label, msg);
  100. }
  101.  
  102. /*    Function Name: AddTreeNode
  103.  *    Description: Adds all nodes below this to the Tree widget.
  104.  *    Arguments: parent - parent of the tree widget.
  105.  *                 top - the top node of the tree.
  106.  *    Returns: the tree widget.
  107.  *
  108.  * NOTE: This is a recursive function.
  109.  */
  110.  
  111. void
  112. AddTreeNode(tree, top) 
  113. Widget tree;
  114. WNode * top;
  115. {
  116.     int i;
  117.     Arg args[1];
  118.     Cardinal num_args = 0;
  119.     char msg[BUFSIZ];
  120.  
  121.     if (top->parent != NULL) {
  122.     if (top->parent->widget == NULL) {
  123.         sprintf( msg, "Loop in tree: node %s's parent (%s) has %s.\n",
  124.             top->name, top->parent->name, "not been created yet");
  125.         SetMessage(global_screen_data.info_label, msg);
  126.     }
  127.     XtSetArg(args[num_args], XtNtreeParent, top->parent->widget);
  128.     num_args++;
  129.     }
  130.  
  131.     top->widget = XtCreateManagedWidget(top->name, toggleWidgetClass, tree,
  132.                     args, num_args);
  133.  
  134.     if (XSaveContext(XtDisplay(top->widget), (Window) top->widget, 
  135.              NODE_INFO, (caddr_t) top) != 0) {
  136.     sprintf( msg, "XSaveContext failed on widget %s.", top->name);
  137.     SetMessage(global_screen_data.info_label, msg);
  138.     }    
  139.  
  140.     XtAddCallback(top->widget, XtNcallback, TreeToggle, (XtPointer) top);
  141.  
  142.     for (i = 0; i < top->num_children; i++) 
  143.     AddTreeNode(tree, top->children[i]);
  144. }
  145.  
  146. /*    Function Name: TreeToggle
  147.  *    Description: Called whenever a tree node is toggled.
  148.  *    Arguments: w - the tree widget.
  149.  *                 node_ptr - pointer to this node's information.
  150.  *                 state_ptr - state of the toggle.
  151.  *    Returns: none.
  152.  */
  153.  
  154. /* ARGSUSED */
  155. void
  156. TreeToggle(w, node_ptr, state_ptr)
  157. Widget w;
  158. caddr_t node_ptr, state_ptr;
  159. {
  160.     Boolean state = (Boolean) state_ptr;
  161.     WNode * node = (WNode *) node_ptr;
  162.  
  163.     if (state) 
  164.     AddNodeToActiveList(node);
  165.     else
  166.     RemoveNodeFromActiveList(node);
  167. }
  168.  
  169. /*    Function Name: AddNodeToActiveList
  170.  *    Description: Adds this node to the list of active toggles.
  171.  *    Arguments: node - node to add.
  172.  *    Returns: none.
  173.  */
  174.  
  175. static void
  176. AddNodeToActiveList(node)
  177. WNode * node;
  178. {
  179.     TreeInfo * info = node->tree_info;
  180.  
  181.     if (IsActiveNode(node))    /* node already active. */
  182.     return;
  183.  
  184.     if (info->num_nodes >= info->alloc_nodes) {
  185.     info->alloc_nodes += NUM_INC;
  186.     info->active_nodes =(WNode **)XtRealloc((XtPointer) info->active_nodes,
  187.                         sizeof(WNode *) * 
  188.                              info->alloc_nodes);
  189.     }
  190.  
  191.     info->active_nodes[info->num_nodes++] = node;
  192. }
  193.  
  194. /*    Function Name: RemoveNodeFromActiveList
  195.  *    Description: Removes a node from the active list.
  196.  *    Arguments: node - node to remove.
  197.  *    Returns: none.
  198.  */
  199.  
  200. static void
  201. RemoveNodeFromActiveList(node)
  202. WNode * node;
  203. {
  204.     TreeInfo * info = node->tree_info;
  205.     Boolean found_node = FALSE;
  206.     int i;
  207.  
  208.     if (!IsActiveNode(node))    /* This node is not active. */
  209.     return;
  210.  
  211.     for (i = 0; i < info->num_nodes; i++) {
  212.     if (found_node)
  213.         info->active_nodes[i - 1] = info->active_nodes[i];
  214.     else if (info->active_nodes[i] == node) 
  215.         found_node = TRUE;
  216.     }
  217.  
  218.     info->num_nodes--;
  219. }
  220.  
  221. /*    Function Name: IsActiveNode
  222.  *    Description: returns TRUE is this node is on the active list.
  223.  *    Arguments: node - node to check.
  224.  *    Returns: see above.
  225.  */
  226.  
  227. static Boolean
  228. IsActiveNode(node)
  229. WNode * node;
  230. {
  231.     TreeInfo * info = node->tree_info;
  232.     int i;
  233.  
  234.     for (i = 0; i < info->num_nodes; i++) 
  235.     if (info->active_nodes[i] == node)
  236.         return(TRUE);
  237.  
  238.     return(FALSE);
  239. }
  240.     
  241. /*    Function Name: CreateTree
  242.  *    Description: Creates a widget tree give a list of names and classes.
  243.  *    Arguments: event - the information from the client.
  244.  *    Returns: The tree_info about this new tree.
  245.  */
  246.     
  247. TreeInfo *
  248. CreateTree(event)
  249. Event * event;
  250. {
  251.     SendWidgetTreeEvent * send_event = (SendWidgetTreeEvent *) event;
  252.     int i;
  253.  
  254.     TreeInfo * tree_info;
  255.  
  256.     tree_info = (TreeInfo *) XtMalloc( (Cardinal) sizeof(TreeInfo));
  257.  
  258.     tree_info->tree_widget = NULL;
  259.     tree_info->top_node = NULL;
  260.     tree_info->active_nodes = NULL;
  261.     tree_info->num_nodes = tree_info->alloc_nodes = 0;
  262.     tree_info->flash_widgets = NULL;
  263.     tree_info->num_flash_widgets = tree_info->alloc_flash_widgets = 0;
  264.  
  265.     for ( i = 0; i < (int)send_event->num_entries; i++)
  266.     AddNode(&(tree_info->top_node), (send_event->info + i), tree_info);
  267.  
  268.     return(tree_info);
  269. }
  270.  
  271. /*    Function Name: PrintNodes
  272.  *    Description: Prints all nodes.
  273.  *    Arguments: top - the top node.
  274.  *    Returns: none.
  275.  */
  276.  
  277. void
  278. PrintNodes(top)
  279. WNode * top;
  280. {
  281.     int i;
  282.  
  283.     if (top->parent == NULL) 
  284.     printf("Top of Tree, Name: %10s, ID: %10ld, Class: %10s\n", 
  285.            top->name, top->id, top->class);
  286.     else
  287.     printf("Parent %10s, Name: %10s, ID: %10ld, Class: %10s\n", 
  288.            top->parent->name, top->name, top->id, top->class);
  289.  
  290.     for (i = 0; i < top->num_children; i++) 
  291.     PrintNodes(top->children[i]);
  292. }
  293.  
  294. /*    Function Name: _TreeRelabel
  295.  *    Description: Modifies the selected elements of the tree
  296.  *    Arguments: tree_info - the tree we are working on.
  297.  *                 type - type of selection to perform
  298.  *    Returns: none.
  299.  */
  300.  
  301. void
  302. _TreeRelabel(tree_info, type)
  303. TreeInfo * tree_info;
  304. LabelTypes type;
  305. {
  306.     WNode * top;
  307.  
  308.     if (tree_info == NULL) {
  309.     SetMessage(global_screen_data.info_label,
  310.            "No widget Tree is avaliable.");
  311.     return;
  312.     }
  313.  
  314.     top = tree_info->top_node;
  315.  
  316.     PrepareToLayoutTree(tree_info->tree_widget); 
  317.     _TreeRelabelNode(top, type, TRUE);
  318.     LayoutTree(tree_info->tree_widget); 
  319. }
  320.  
  321. /*    Function Name: _TreeSelect
  322.  *    Description: Activates relatives of the active nodes, as specified
  323.  *                   by type, or Selects all nodes as specified by type.
  324.  *    Arguments: tree_info - information about the tree to work on.
  325.  *                 type - type of activate to invode.
  326.  *    Returns: none.
  327.  */
  328.  
  329. void
  330. _TreeSelect(tree_info, type)
  331. TreeInfo * tree_info;
  332. SelectTypes type;
  333. {
  334.     WNode ** active_nodes;
  335.     Cardinal num_active_nodes;
  336.     int i;
  337.  
  338.     if (tree_info == NULL) {
  339.     SetMessage(global_screen_data.info_label,
  340.            "No widget Tree is avaliable.");
  341.     return;
  342.     }
  343.  
  344.     switch(type) {
  345.     case SelectNone:
  346.     case SelectAll:
  347.     case SelectInvert:
  348.     _TreeSelectNode(tree_info->top_node, type, TRUE);
  349.     return;
  350.     default:
  351.     break;            /* otherwise continue. */
  352.     }
  353.  
  354.     if (tree_info->num_nodes == 0) {
  355.     SetMessage(global_screen_data.info_label,
  356.            "There are no active nodes.");
  357.     return;
  358.     }
  359.  
  360.     active_nodes = CopyActiveNodes(tree_info);
  361.     num_active_nodes = tree_info->num_nodes;
  362.  
  363.     for (i = 0; i < num_active_nodes; i++)
  364.     _TreeActivateNode(active_nodes[i], type);
  365.  
  366.     XtFree((XtPointer) active_nodes);
  367. }
  368.  
  369. /*    Function Name: _TreeSelectNode
  370.  *    Description: Modifies the state of a node and all its decendants.
  371.  *    Arguments: node - node to operate on.
  372.  *                 type - type of selection to perform.
  373.  *                 recurse - whether to continue on down the tree.
  374.  *    Returns: none.
  375.  */
  376.  
  377. void
  378. _TreeSelectNode(node, type, recurse)
  379. WNode * node;
  380. SelectTypes type;
  381. Boolean recurse;
  382. {
  383.     int i;
  384.     Arg args[1];
  385.     Boolean state;
  386.  
  387.     switch(type) {
  388.     case SelectAll:
  389.     state = TRUE;
  390.     break;
  391.     case SelectNone:
  392.     state = FALSE;
  393.     break;
  394.     case SelectInvert:
  395.     XtSetArg(args[0], XtNstate, &state);
  396.     XtGetValues(node->widget, args, ONE);
  397.     
  398.     state = !state;
  399.     break;
  400.     default:
  401.     SetMessage(global_screen_data.info_label,
  402.            "Internal Error: Unknown select type.");
  403.     return;
  404.     }
  405.  
  406.     XtSetArg(args[0], XtNstate, state);
  407.     XtSetValues(node->widget, args, ONE);
  408.     TreeToggle(node->widget, (XtPointer) node, (XtPointer) state);
  409.  
  410.     if (!recurse)
  411.     return;
  412.  
  413.     for (i = 0; i < node->num_children; i++) 
  414.     _TreeSelectNode(node->children[i], type, recurse);
  415. }
  416.  
  417. /*    Function Name: _TreeRelabelNodes
  418.  *    Description: Modifies the node and all its decendants label.
  419.  *    Arguments: node - node to operate on.
  420.  *                 type - type of selection to perform.
  421.  *                 recurse - whether to continue on down the tree.
  422.  *    Returns: none.
  423.  */
  424.  
  425. void
  426. _TreeRelabelNode(node, type, recurse)
  427. WNode * node;
  428. LabelTypes type;
  429. Boolean recurse;
  430. {
  431.     int i;
  432.     Arg args[1];
  433.     char buf[30];
  434.     char *label;
  435.  
  436.     switch(type) {
  437.     case ClassLabel:
  438.     XtSetArg(args[0], XtNlabel, node->class);
  439.     break;
  440.     case NameLabel:
  441.     XtSetArg(args[0], XtNlabel, node->name);
  442.     break;
  443.     case IDLabel:
  444.     sprintf(buf, "id: 0x%lx", node->id);
  445.     XtSetArg(args[0], XtNlabel, buf);
  446.     break;
  447.     case WindowLabel:
  448.     if (node->window == EDITRES_IS_UNREALIZED) 
  449.         strcpy(buf, "unrealized widget");
  450.     else if (node->window == EDITRES_IS_OBJECT) 
  451.         strcpy(buf, "non windowed object");        
  452.     else
  453.         sprintf(buf, "win: 0x%lx", node->window);
  454.         
  455.     XtSetArg(args[0], XtNlabel, buf);
  456.     break;
  457.     case ToggleLabel:
  458.     XtSetArg(args[0], XtNlabel, &label);
  459.     XtGetValues(node->widget, args, ONE);
  460.     if (label && !strcmp(label, node->name))
  461.         XtSetArg(args[0], XtNlabel, node->class);
  462.     else
  463.         XtSetArg(args[0], XtNlabel, node->name);
  464.     break;
  465.     default:
  466.     SetMessage(global_screen_data.info_label,
  467.            "Internal Error: Unknown label type.");
  468.     return;
  469.     }
  470.  
  471.     XtSetValues(node->widget, args, ONE);
  472.  
  473.     if (!recurse)
  474.     return;
  475.  
  476.     for (i = 0; i < node->num_children; i++) 
  477.     _TreeRelabelNode(node->children[i], type, recurse);
  478. }
  479.  
  480. /*    Function Name: _TreeActivateNode
  481.  *    Description: Activates relatives of the node specfied, as specified
  482.  *                   by type.
  483.  *    Arguments: node - node to opererate on.
  484.  *                 type - type of activate to invode.
  485.  *    Returns: none.
  486.  */
  487.  
  488. void
  489. _TreeActivateNode(node, type)
  490. WNode * node;
  491. SelectTypes type;
  492. {
  493.     Arg args[1];
  494.     int i;
  495.  
  496.     XtSetArg(args[0], XtNstate, TRUE);
  497.  
  498.     if ((type == SelectParent) || (type == SelectAncestors)) {
  499.     node = node->parent;
  500.     if (node == NULL)
  501.         return;
  502.  
  503.     XtSetValues(node->widget, args, ONE);    
  504.     AddNodeToActiveList(node);
  505.  
  506.     if (type == SelectAncestors)
  507.         _TreeActivateNode(node, type);    
  508.     }
  509.     else if ((type == SelectChildren) || (type == SelectDescendants)) 
  510.     for (i = 0; i < node->num_children; i++) {
  511.         AddNodeToActiveList(node->children[i]);
  512.         XtSetValues(node->children[i]->widget, args, ONE);
  513.         if (type == SelectDescendants)
  514.         _TreeActivateNode(node->children[i], type);
  515.     }
  516.     else
  517.     SetMessage(global_screen_data.info_label,
  518.            "Internal Error: Unknown activate type.");    
  519. }
  520.  
  521. /************************************************************
  522.  *
  523.  * Non - Exported Functions. 
  524.  *
  525.  ************************************************************/
  526.  
  527. WNode * FindNode();
  528.  
  529. /*    Function Name: AddNode
  530.  *    Description: adds a node to the widget tree.
  531.  *    Arguments: top_node - a pointer to the current top node.
  532.  *                 info - the info from the client about the widget tree.
  533.  *                 tree_info - global information on this tree.
  534.  *    Returns: none.
  535.  */
  536.  
  537. static void
  538. AddNode(top_node, info, tree_info)
  539. WNode ** top_node;
  540. WidgetTreeInfo * info;
  541. TreeInfo * tree_info;
  542. {
  543.     WNode *node, *parent;
  544.     Boolean early_break = FALSE;
  545.     Cardinal number = info->widgets.num_widgets;
  546.  
  547.     if ( (node = FindNode(*top_node, info->widgets.ids, number)) == NULL) {
  548.     node = (WNode *) XtCalloc(sizeof(WNode), ONE);
  549.  
  550.     node->id = info->widgets.ids[number - 1];
  551.     FillNode(info, node, tree_info);
  552.  
  553.     for ( number--; number > 0; number--, node = parent) {
  554.         parent = FindNode(*top_node, info->widgets.ids, number);
  555.         if (parent == NULL) {
  556.         parent = (WNode *) XtCalloc(sizeof(WNode), ONE);
  557.         parent->id = info->widgets.ids[number - 1];
  558.         }
  559.         else
  560.         early_break = TRUE;
  561.  
  562.         AddChild(parent, node);
  563.  
  564.         if (early_break) 
  565.         break;
  566.     }
  567.  
  568.     if (!early_break) {
  569.         if (node->parent == NULL)
  570.         *top_node = node;
  571.         else
  572.         *top_node = node->parent;
  573.     }
  574.     }
  575.     else
  576.     FillNode(info, node, tree_info);
  577. }
  578.  
  579. /*    Function Name: FillNode
  580.  *    Description: Fills in everything but the node id in the node.
  581.  *    Arguments: info - the info from the client.
  582.  *                 node - node to fill.
  583.  *                 tree_info - global information on this tree.
  584.  *    Returns: none
  585.  */
  586.  
  587. static void
  588. FillNode(info, node, tree_info)
  589. WidgetTreeInfo * info;
  590. WNode * node;
  591. TreeInfo * tree_info;
  592. {
  593.     node->class = info->class;
  594.     info->class = NULL;    /* keeps it from deallocating. */
  595.     node->name = info->name;
  596.     info->name = NULL;
  597.     node->window = info->window;
  598.     node->tree_info = tree_info;
  599. }
  600.  
  601. /*    Function Name: AddChild
  602.  *    Description: Adds a child to an existing node.
  603.  *    Arguments: parent - parent node.
  604.  *                 child - child node to add.
  605.  *    Returns: none.
  606.  */
  607.  
  608. static void
  609. AddChild(parent, child)
  610. WNode * parent, * child;
  611. {
  612.     if (parent->num_children >= parent->alloc_children) {
  613.     parent->alloc_children += NUM_INC;
  614.     parent->children = (WNode **) XtRealloc((char *)parent->children, 
  615.                      sizeof(WNode *) * parent->alloc_children);
  616.     }
  617.  
  618.     parent->children[parent->num_children] = child;
  619.     (parent->num_children)++;
  620.  
  621.     child->parent = parent;
  622. }
  623.  
  624. /************************************************************
  625.  *
  626.  *  Functions that operate of the current tree.
  627.  * 
  628.  ************************************************************/
  629.     
  630. /*    Function Name: CopyActiveNodes
  631.  *    Description: returns a copy of the currently selected nodes.
  632.  *    Arguments: tree_info - the tree info struct.
  633.  *    Returns: a copy of the selected nodes.
  634.  */
  635.  
  636. static WNode ** 
  637. CopyActiveNodes(tree_info)
  638. TreeInfo * tree_info;
  639. {
  640.     WNode ** list;
  641.     int i;
  642.  
  643.     if ( (tree_info == NULL) || (tree_info->num_nodes == 0))
  644.     return(NULL);
  645.  
  646.     list = (WNode **) XtMalloc(sizeof(WNode *) * tree_info->num_nodes);
  647.  
  648.     for (i = 0; i < tree_info->num_nodes; i++)
  649.     list[i] = tree_info->active_nodes[i];
  650.  
  651.     return(list);
  652. }
  653.  
  654. /*    Function Name: SetAndCenterTreeNode
  655.  *    Description: Deactivates all nodes, activates the one specified, and
  656.  *                   and moves the tree to be centered on the current node.
  657.  *    Arguments: node - node to use.
  658.  *    Returns: none.
  659.  */
  660.  
  661. void
  662. SetAndCenterTreeNode(node)
  663. WNode * node;
  664. {
  665.     Arg args[5];
  666.     Cardinal num_args;
  667.     Position node_x, node_y;
  668.     Dimension port_width, port_height;
  669.     Dimension node_width, node_height, node_bw;
  670.  
  671.     _TreeSelect(node->tree_info, SelectNone); /* Unselect all nodes */
  672.     _TreeSelectNode(node, SelectAll, FALSE);  /* Select this node */
  673.  
  674.     /*
  675.      * Get porthole dimensions.
  676.      */
  677.  
  678.     num_args = 0;
  679.     XtSetArg(args[num_args], XtNwidth, &port_width); num_args++;
  680.     XtSetArg(args[num_args], XtNheight, &port_height); num_args++;
  681.     XtGetValues(XtParent(node->tree_info->tree_widget), args, num_args);
  682.  
  683.     /*
  684.      * Get node widget dimensions.
  685.      */
  686.  
  687.     num_args = 0;
  688.     XtSetArg(args[num_args], XtNwidth, &node_width); num_args++;
  689.     XtSetArg(args[num_args], XtNheight, &node_height); num_args++;
  690.     XtSetArg(args[num_args], XtNborderWidth, &node_bw); num_args++;
  691.     XtSetArg(args[num_args], XtNx, &node_x); num_args++;
  692.     XtSetArg(args[num_args], XtNy, &node_y); num_args++;
  693.     XtGetValues(node->widget, args, num_args);
  694.  
  695.     /*
  696.      * reset the node x and y location to be the new x and y location of
  697.      * the tree relative to the porthole.
  698.      */
  699.  
  700.     node_x = port_width/2 - (node_x + node_width/2 + node_bw);
  701.     node_y = port_height/2 - (node_y + node_height/2 + node_bw);
  702.  
  703.     num_args = 0;
  704.     XtSetArg(args[num_args], XtNx, node_x); num_args++;
  705.     XtSetArg(args[num_args], XtNy, node_y); num_args++;
  706.     XtSetValues(node->tree_info->tree_widget, args, num_args);    
  707. }
  708.  
  709. /*    Function Name: PerformTreeToFileDump
  710.  *    Description: Dumps the contents of the current widget tree to
  711.  *                   the file specified. 
  712.  *    Arguments: node - node to dump.
  713.  *                 num_tabs - number of spaces to indent.
  714.  *                 fp - pointer to the file to write to.
  715.  *    Returns: none.
  716.  */
  717.  
  718. void
  719. PerformTreeToFileDump(node, num_tabs, fp)
  720. WNode * node;
  721. int num_tabs;
  722. FILE * fp;
  723. {
  724.     int i;
  725.  
  726.     for (i = 0; i < num_tabs; i++) 
  727.     fprintf(fp, "\t");
  728.     fprintf(fp, "%s  %s\n", node->class, node->name);
  729.  
  730.     num_tabs++;
  731.     for (i = 0; i < node->num_children; i++)
  732.     PerformTreeToFileDump(node->children[i], num_tabs, fp);
  733. }
  734.  
  735.